package mn.idax.exchange.otc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import mn.idax.exchange.otc.domain.MessageNotifyDTO;
import mn.idax.exchange.otc.domain.OrderChat;
import mn.idax.exchange.otc.domain.UpdateMessage;
import mn.idax.exchange.otc.entity.JPushLog;
import mn.idax.exchange.otc.entity.JPushMessage;
import mn.idax.exchange.otc.entity.JPushMessageExample;
import mn.idax.exchange.otc.enums.LogTypeEnum;
import mn.idax.exchange.otc.service.*;
import mn.idax.exchange.otc.util.DateUtils;
import mn.idax.exchange.otc.util.I18nUtil;
import mn.idax.exchange.otc.vo.MessageDTO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: jack_huang
 * @Date: 2019/5/27 14:03
 */
@Service
public class MessageServiceImpl implements MessageService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageServiceImpl.class);

    /**
     * 极光推送模板支持的语言
     */
    private static final String[] SUPPORT_LANG ={"zh_cn","en_us","ja_jp","ko_kr","zh_tw"};

    @Autowired
    private JPushLogService jPushLogService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private FileUrlService fileUrlService;

    @Override
    public List<MessageDTO> getSystemMessage(Integer userId,String lang) {

        //获取.net极光推送的系统消息
        List<JPushLog> systemJpushLog = jPushLogService.getSystemMessage(userId);

        List<MessageDTO> list = new ArrayList<>();

        if (!systemJpushLog.isEmpty()){
            for (JPushLog jPushLog : systemJpushLog) {
                MessageDTO messageDTO = new MessageDTO();
                //db jpushlog 主键
                messageDTO.setMessageId(jPushLog.getId().toString());
                messageDTO.setMessage(formateMsgBody(jPushLog, lang));
                messageDTO.setReadFlag(jPushLog.getReadFlag());
                messageDTO.setIdentityFlag(0);
                messageDTO.setBusiness(jPushLog.getBusiness());
                messageDTO.setSaveArea(1);
                messageDTO.setSendTime(DateUtils.getDateToStrCorrect(jPushLog.getCreatetime(),"yyyy-MM-dd'T'HH:mm:ss"));
                list.add(messageDTO);
            }
        }

        //获取otc 的系统消息 广告上下架
        Query query = new Query();
        query.addCriteria(Criteria.where("receiver").is(userId).and("skipType").is("ad_detail").and("readFlag").in(0,1));
        Sort sort = new Sort(Sort.Direction.DESC, "sendTime");
        List<MessageNotifyDTO> allMessage = mongoTemplate.find(query.with(sort), MessageNotifyDTO.class);

        if (!allMessage.isEmpty()){
            for (MessageNotifyDTO messageNotifyDTO : allMessage) {
                MessageDTO messageDTO = new MessageDTO();
                messageDTO.setMessageId(messageNotifyDTO.getMessageId());
                messageDTO.setMessage(I18nUtil.getMessage(messageNotifyDTO.getBody(), lang, messageNotifyDTO.getDynamicParam()));
                messageDTO.setReadFlag(messageNotifyDTO.getReadFlag());
                messageDTO.setIdentityFlag(0);
                messageDTO.setBusiness(0);
                messageDTO.setSaveArea(0);
                messageDTO.setSendTime(DateUtils.getTimeByTimeStamp(messageNotifyDTO.getSendTime()));
                list.add(messageDTO);
            }
        }

        Collections.sort(list);

        return list;

    }


    /**
     * 更新mongo中消息为已读
     * @param userId
     */
    @Override
    public void updateSystemMessage(UpdateMessage updateMessage, Integer userId) {

        Integer updateTotal = 0;
        if (updateMessage.getSaveArea().equals(0)){
            Query query = new Query();
            query.addCriteria(new Criteria().andOperator(
                    Criteria.where("messageId").is(updateMessage.getMessageId())));

            List<MessageNotifyDTO> allMessage = mongoTemplate.find(query, MessageNotifyDTO.class);
            LOGGER.info("systemMessageNeedUpdate data {}",JSON.toJSONString(allMessage));
            Update update = new Update();
            update.set("readFlag", 1);
            updateTotal = mongoTemplate.updateMulti(query, update, MessageNotifyDTO.class).getN();
        } else {
            Integer id = Integer.valueOf(updateMessage.getMessageId());
            Date utcNow = DateUtils.getUTCNow();

            updateTotal = jPushLogService.updateJpushLog(id,utcNow);
            LOGGER.info("updateJpushLogSystemMessage one data ,request params id {}, result update {}",id,updateTotal);
        }

    }

    /**
     * 获取聊天消息
     * @param lang
     * @param userId
     * @return
     */
    @Override
    public List<MessageDTO> getChatMessage(String lang, Integer userId) {

        List<MessageDTO> list = new ArrayList<>();

        //查出与我相关的所有订单消息
        Query query = new Query();
        Criteria criteria = new Criteria().orOperator(Criteria.where("buyerId").is(userId).and("buyerReadFlag").in(0,1), Criteria.where("sellerId").is(userId).and("sellerReadFlag").in(0,1));
        Sort sort = new Sort(Sort.Direction.DESC, "sendTime");
        query.addCriteria(criteria);
        List<OrderChat> allOrderChats = mongoTemplate.find(query.with(sort), OrderChat.class);

        LOGGER.info("queryChatMessage data {}",JSON.toJSONString(allOrderChats));
        Map<String, OrderChat> unReadOrderChatMap = allOrderChats.stream().collect(Collectors.toMap(OrderChat::getOrderNum, Function.identity(), (key1, key2) -> key1));

        if (!CollectionUtils.isEmpty(unReadOrderChatMap)){
            for (String orderNum : unReadOrderChatMap.keySet()) {
                OrderChat orderChat = unReadOrderChatMap.get(orderNum);
                MessageDTO messageDTO = new MessageDTO();
                BeanUtils.copyProperties(orderChat,messageDTO);
                messageDTO.setReadFlag(userId.equals(orderChat.getBuyerId()) ? orderChat.getBuyerReadFlag() : orderChat.getSellerReadFlag());
                messageDTO.setIdentityFlag(userId.equals(orderChat.getBuyerId()) ? 1 : 2);
                messageDTO.setSaveArea(0);
                messageDTO.setSendTime(DateUtils.getTimeByTimeStamp(orderChat.getSendTime()));
                if (orderChat.getLogType().equals(LogTypeEnum.system)){
                    messageDTO.setMessage(I18nUtil.getMessage(orderChat.getMessage() , lang,  orderChat.getDynamicParam()));
                }
                //采用orderNum pc端可以调用 更新已读的信息
                messageDTO.setMessageId(orderChat.getOrderNum());
                messageDTO.setUserLogo(fileUrlService.dealFileUrlAddress(orderChat.getUserLogo()));
                list.add(messageDTO);
            }
        }

        Collections.sort(list);

        return list;
    }

    /**
     * 更新聊天消息
     * @param userId
     * @param updateMessage
     * @return
     */
    @Override
    public void updateChatMessage(UpdateMessage updateMessage, Integer userId) {

        Query query = new Query();
        query.addCriteria(new Criteria().andOperator(
                Criteria.where("orderNum").is(updateMessage.getMessageId())));

        OrderChat orderChat = mongoTemplate.findOne(query, OrderChat.class);

        if (orderChat != null){
            Query updateMongo = new Query();
            Update update = new Update();
            if (userId.equals(orderChat.getBuyerId())){
                updateMongo.addCriteria(new Criteria().andOperator(Criteria.where("orderNum").is(orderChat.getOrderNum())
                        .and("buyerReadFlag").is(0)));
                update.set("buyerReadFlag", 1);
            } else {
                updateMongo.addCriteria(new Criteria().andOperator(Criteria.where("orderNum").is(orderChat.getOrderNum())
                        .and("sellerReadFlag").is(0)));
                update.set("sellerReadFlag", 1);
            }

            int n = mongoTemplate.updateMulti(updateMongo, update, OrderChat.class).getN();
        }

    }

    /**
     * 消息一键已读
     * @param userId
     */
    @Override
    public void updateAllMessageToRead(Integer userId) {

        //获取数据库中的未读消息
        List<Integer> unReadSystemMessage = jPushLogService.getUnReadSystemMessage(userId);

        //获取mongo中未读的系统消息
        Query adQuery = new Query();
        adQuery.addCriteria(Criteria.where("receiver").is(userId).and("skipType").is("ad_detail").and("readFlag").is(0));
        List<MessageNotifyDTO> adUnReads = mongoTemplate.find(adQuery, MessageNotifyDTO.class);

        //获取mongo中未读的聊天消息
        Query chatAsBuyerQuery = new Query();
        chatAsBuyerQuery.addCriteria(Criteria.where("buyerId").is(userId).and("buyerReadFlag").is(0));
        List<OrderChat> buyerUnReads = mongoTemplate.find(chatAsBuyerQuery, OrderChat.class);

        //作更新
        Query chatAsSellerQuery = new Query();
        chatAsSellerQuery.addCriteria(Criteria.where("sellerId").is(userId).and("sellerReadFlag").is(0));
        List<OrderChat> sellerUnReads = mongoTemplate.find(chatAsSellerQuery, OrderChat.class);

        if (!unReadSystemMessage.isEmpty()){
            Date utcNow = DateUtils.getUTCNow();
            jPushLogService.updateJpushLogsToRead(unReadSystemMessage,utcNow);
        }

        if (!adUnReads.isEmpty()){
            Update update = new Update();
            update.set("readFlag", 1);
            mongoTemplate.updateMulti(adQuery, update, MessageNotifyDTO.class).getN();
        }

        if (!buyerUnReads.isEmpty()){
            Update update = new Update();
            update.set("buyerReadFlag", 1);
            mongoTemplate.updateMulti(chatAsBuyerQuery, update, OrderChat.class).getN();
        }

        if (!sellerUnReads.isEmpty()){
            Update update = new Update();
            update.set("sellerReadFlag", 1);
            mongoTemplate.updateMulti(chatAsSellerQuery, update, OrderChat.class).getN();
        }

    }

    /**
     * 格式化jpuhlog中要发送or显示的数据
     * @param receiveData
     * @return
     */
    private String formateMsgBody(JPushLog receiveData, String lang) {

        JPushMessage jPushMessage = MemoryService.JPUSHTEMPLATE.get(receiveData.getBusiness().toString().concat(lang));

        String format = "";
        if(null == jPushMessage){
            LOGGER.error("formateJPushLog error,receive data is {}", JSON.toJSONString(receiveData));
        } else{

            String parameter = receiveData.getParameter();

            if (StringUtils.isEmpty(parameter) ){
                format = MessageFormat.format(jPushMessage.getMsgtext(),null);
            } else {
                Map map = JSON.parseObject(parameter, Map.class);
                Object data = map.get("data");
                if (Objects.isNull(data)){
                    format = MessageFormat.format(jPushMessage.getMsgtext(),null);
                } else {
                    JSONArray jsonArray = (JSONArray)data;
                    format = MessageFormat.format(jPushMessage.getMsgtext(), jsonArray.toArray());
                }

            }
        }
        return format;
    }
}
